{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 线程通信"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 学习目标"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- 核心掌握：理解线程通信（条件变量与信号量）的实际应用场景与实现原理\n",
    "- 能力要求：能够区分线程互斥与通信的差异，并正确使用同步机制\n",
    "- 面试重点：掌握多线程环境下临界区保护的实现方法（含无锁编程）"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 线程互斥"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "线程互斥概念\n",
    "\n",
    "- 本质问题：多个线程访问共享资源时产生的竞态条件（Race Condition）\n",
    "- 临界区特征：\n",
    "  - 不可重入性：当代码段存在竞态条件时，不允许并发执行\n",
    "  - 原子操作要求：必须保证对共享资源的操作不可分割\n",
    "- 典型场景：\n",
    "  - 危险操作：非原子化的`count++`实际对应多条汇编指令（`MOV/ADD/MOV`）\n",
    "  - 结果不确定性：线程调度顺序不同会导致最终结果不一致"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "同步机制实现\n",
    "\n",
    "- 互斥锁方案：\n",
    "  - 基础锁：`mutex`、`lock_guard`（RAII封装）\n",
    "  - 高级锁：`try_lock`（避免死锁）、乐观锁\n",
    "  - 特性：通过阻塞线程实现同步，可能引发活锁问题\n",
    "- 无锁编程：\n",
    "  - CAS操作：Compare-And-Swap 原子指令实现无锁队列/链表\n",
    "  - 适用场景：高并发读多写少环境（如Disruptor框架）\n",
    "- 线程数量：通常按CPU核心数配置（Golang/Rust最佳实践）"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "线程通信机制\n",
    "\n",
    "- 与互斥的区别：\n",
    "  - 研究对象：仍为多线程，但关注不同代码块间的协作\n",
    "  - 核心目标：实现线程间的状态通知而非资源保护\n",
    "- 条件变量：\n",
    "  - 作用：当特定条件满足时唤醒等待线程\n",
    "  - 使用要点：必须配合互斥锁使用（避免唤醒丢失问题）\n",
    "- 信号量：\n",
    "  - 控制逻辑：通过计数器控制并发访问量\n",
    "  - 经典应用：生产者-消费者模型、线程池任务调度"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 重点总结"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- 面试考点：\n",
    "  - 竞态条件的产生条件与解决方案\n",
    "  - 可重入函数与线程安全的关系\n",
    "  - CAS操作在无锁数据结构中的应用\n",
    "- 实践建议：\n",
    "  - 临界区应尽量缩小范围（减少锁竞争）\n",
    "  - 优先考虑无锁设计，必要时使用原子类型\n",
    "  - 条件变量使用前必须验证谓词条件（避免虚假唤醒）"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 线程通信概念"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "线程通信的本质\n",
    "\n",
    "- 执行时序不可控性：线程调度完全由操作系统内核控制，不能假设线程A/B的执行先后顺序。\n",
    "- 依赖关系：当线程A的代码执行需要等待线程B完成特定操作时，就产生了线程间的执行依赖。\n",
    "- 通信需求：需要通过特定机制让线程B完成任务后通知线程A继续执行。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "条件变量的工作原理\n",
    "\n",
    "- 等待机制(wait)：\n",
    "  - 当线程A发现条件不满足时，主动进入等待状态\n",
    "  - 等待期间线程A会被移出就绪队列，不再参与调度\n",
    "- 通知机制(notify)：\n",
    "  - 线程B完成任务后发出通知\n",
    "  - 通知所有等待该条件的线程条件已满足\n",
    "- 恢复执行：\n",
    "  - 被通知的线程重新进入就绪队列\n",
    "  - 再次被调度时检查条件确实满足后继续执行"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "线程互斥与通信的区别\n",
    "\n",
    "- 互斥锁(mutex)：\n",
    "  - 解决多个线程能否同时进入同一代码段的问题\n",
    "  - 保证临界区代码的原子性执行\n",
    "- 线程通信：\n",
    "  - 解决不同线程间代码块的执行顺序问题\n",
    "  - 通过条件变量/信号量实现线程间的执行依赖\n",
    "- 关键区别：\n",
    "  - 互斥关注的是\"能不能同时执行\"\n",
    "  - 通信关注的是\"谁先执行谁后执行\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 条件变量"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- 两种实现方式：\n",
    "  - Linux系统提供的`pthread_cond_t`\n",
    "  - C++11线程库中的`condition_variable`\n",
    "- 使用原则：在C++项目中优先使用语言级别的实现（C++11版本）\n",
    "- 依赖关系：必须与互斥锁配合使用，单独无法发挥作用"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "生产者消费者模型\n",
    "\n",
    "- 基本概念：\n",
    "  - 生产者线程负责向容器添加数据\n",
    "  - 消费者线程负责从容器取出数据\n",
    "  - 两者通过共享容器进行通信\n",
    "- 控制方式：\n",
    "  - 场景一：批量生产后批量消费（控制较粗）\n",
    "  - 场景二：生产一个消费一个（控制精细）\n",
    "- 容器特性：C++ STL容器本身非线程安全，需自行添加同步机制"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "逻辑实现\n",
    "\n",
    "- 核心组件：\n",
    "  - `mutex`：互斥锁（必须使用`unique_lock`而非`lock_guard`）\n",
    "  - `condition_variable`：条件变量\n",
    "- `wait`操作的双重作用：\n",
    "  - 改变线程状态为等待\n",
    "  - 自动释放关联的互斥锁\n",
    "- 生产者逻辑：\n",
    "  - 获取锁\n",
    "  - 检查容器是否满\n",
    "  - 若满则`wait`（释放锁+等待）\n",
    "  - 生产数据\n",
    "  - `notify_all`通知消费者\n",
    "- 消费者逻辑：\n",
    "  - 获取锁\n",
    "  - 检查容器是否空\n",
    "  - 若空则`wait`（释放锁+等待）\n",
    "  - 消费数据\n",
    "  - `notify_all`通知生产者\n",
    "- 关键点：\n",
    "  - 使用`unique_lock`允许手动释放锁\n",
    "  - `wait`操作避免\"占着茅坑不拉屎\"的死锁情况\n",
    "  - 通知机制确保线程及时唤醒"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "C++17",
   "language": "C++17",
   "name": "xcpp17"
  },
  "language_info": {
   "name": "C++17"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
